﻿using System.Collections.Generic;
using System.Common;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

namespace System
{
    /// <summary>
    /// 对象扩展
    /// </summary>
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public static class ObjectExtension
    {
        #region System.Drawing.Image

        /// <summary>
        /// 将图像转换为字节格式
        /// </summary>
        /// <param name="image">要转换的图像</param>
        /// <returns>转换后的字节数组</returns>
        public static byte[] ToBytes(this Image image)
        {
            return ToBytes(image, ImageFormat.Png);
        }

        /// <summary>
        /// 将图像转换为字节格式
        /// </summary>
        /// <param name="image">要转换的图像</param>
        /// <returns>转换后的字节数组</returns>
        public static byte[] ToBytes(this Image image, System.Drawing.Imaging.ImageFormat format)
        {
            if (image == null) return null;

            using (var ms = new System.IO.MemoryStream())
            {
                image.Save(ms, format);
                ms.Close();

                return ms.ToArray();
            }
        }

        /// <summary>
        /// 使用质量90将图片保存到指定位置为JPEG图片
        /// </summary>
        /// <param name="image">要保存的图片</param>
        /// <param name="path">保存的路径</param>
        public static void SaveAsJpeg(this Image image, string path)
        {
            SaveAsJpeg(image, path, 90);
        }

        /// <summary>
        /// 使用指定的图片质量将图片保存到指定位置为JPEG图片
        /// </summary>
        /// <param name="image">要保存的图片</param>
        /// <param name="path">保存的路径</param>
        /// <param name="quality">质量</param>
        public static void SaveAsJpeg(this Image image, string path, int quality)
        {
            EncoderParameters parameters = new EncoderParameters(1);
            parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ((long)quality));

            ImageCodecInfo myImageCodecInfo = (from p in ImageCodecInfo.GetImageEncoders() where p.MimeType == "image/jpeg" select p).Single<ImageCodecInfo>();
            image.Save(path, myImageCodecInfo, parameters);
        }

        /// <summary>
        /// 由原始的小图创建一个居中的大图
        /// </summary>
        /// <param name="image">原始图像</param>
        /// <param name="width">新图像的宽度</param>
        /// <param name="height">新图像的高度</param>
        /// <returns><see cref="T:System.Drawing.Image"/></returns>
        public static Image ResizeWithMargin(this Image image, int width, int height)
        {
            if (image == null || image.Width >= width || image.Height >= height) return image;

            var nimg = new Bitmap(width, height);
            using (var g = Graphics.FromImage(nimg))
            {
                g.DrawImage(image, (width - image.Width) / 2, (height - image.Height) / 2, image.Height, image.Width);
            }

            return nimg;
        }

        #endregion System.Drawing.Image

        #region System.Drawing.Color

        /// <summary>
        /// 获得颜色的WEB RGB表示形式（如#000000）
        /// </summary>
        /// <param name="color">颜色</param>
        /// <param name="upperCase">是否使用大写。默认为 <see langword="true" /></param>
        /// <returns>对应的 <see langword="string" /></returns>
        public static string ToWebRgbColor(this Color color, bool upperCase = true)
        {
            var format = upperCase ? "X2" : "x2";
            return "#" + color.R.ToString(format) + color.G.ToString(format) + color.B.ToString(format);
        }

        /// <summary>
        /// 获得颜色的WEB RGB表示形式（如 rgba(255,255,255,1)）
        /// </summary>
        /// <param name="color">颜色</param>
        /// <returns>对应的 <see langword="string" /></returns>
        public static string ToWebRgbaColor(this Color color)
        {
            return "rgba(" + color.R + "," + color.G + "," + color.B + "," + (color.A / 255.0).ToString("#0.00") + ")";
        }

        #endregion System.Drawing.Color

        #region Reflection

        ///// <summary>
        ///// 根据指定的自定义属性来过滤类型列表
        ///// </summary>
        ///// <typeparam name="T">要查找的自定义属性类型</typeparam>
        ///// <param name="assembly">程序集</param>
        ///// <returns>查找到的结果</returns>
        //public static Dictionary<Type, T[]> GetFilteredTypeWithCustomerAttribute<T>(this Assembly assembly)
        //{
        //    var dic = assembly.GetTypes().ToDictionary(s => s, s => s.GetCustomAttributes(typeof(T), true).Cast<T>().ToArray());
        //    dic.Keys.Where(s => dic[s].Length == 0).ToArray().ForEach(s => dic.Remove(s));
        //    return dic;
        //}

        ///// <summary>
        ///// 根据指定的自定义属性来过滤方法列表
        ///// </summary>
        ///// <typeparam name="T">要查找的自定义属性类型</typeparam>
        ///// <param name="type">程序集</param>
        ///// <returns>查找到的结果</returns>
        //public static Dictionary<MethodInfo, T[]> GetFilteredMethodWithCustomerAttribute<T>(this Type type)
        //{
        //    return GetFilteredMethodWithCustomerAttribute<T>(type, BindingFlags.Public | BindingFlags.Instance);
        //}

        ///// <summary>
        ///// 根据指定的自定义属性来过滤方法列表
        ///// </summary>
        ///// <typeparam name="T">要查找的自定义属性类型</typeparam>
        ///// <param name="flags">查找的标志位</param>
        ///// <param name="type">程序集</param>
        ///// <returns>查找到的结果</returns>
        //public static Dictionary<MethodInfo, T[]> GetFilteredMethodWithCustomerAttribute<T>(this Type type, BindingFlags flags)
        //{
        //    var dic = type.GetMethods(flags).ToDictionary(s => s, s => s.GetCustomAttributes(typeof(T), true).Cast<T>().ToArray());
        //    dic.Keys.Where(s => dic[s].Length == 0).ToArray().ForEach(s => dic.Remove(s));
        //    return dic;
        //}

        ///// <summary>
        ///// 根据指定的自定义属性来过滤属性列表
        ///// </summary>
        ///// <typeparam name="T">要查找的自定义属性类型</typeparam>
        ///// <param name="type">程序集</param>
        ///// <returns>查找到的结果</returns>
        //public static Dictionary<PropertyInfo, T[]> GetFilteredPropertyWithCustomerAttribute<T>(this Type type)
        //{
        //    return GetFilteredPropertyWithCustomerAttribute<T>(type, BindingFlags.Public | BindingFlags.Instance);
        //}

        ///// <summary>
        ///// 根据指定的自定义属性来过滤属性列表
        ///// </summary>
        ///// <typeparam name="T">要查找的自定义属性类型</typeparam>
        ///// <param name="type">程序集</param>
        ///// <param name="flags">查找的标志位</param>
        ///// <returns>查找到的结果</returns>
        //public static Dictionary<PropertyInfo, T[]> GetFilteredPropertyWithCustomerAttribute<T>(this Type type, BindingFlags flags)
        //{
        //    var dic = type.GetProperties(flags).ToDictionary(s => s, s => s.GetCustomAttributes(typeof(T), true).Cast<T>().ToArray());
        //    dic.Keys.Where(s => dic[s].Length == 0).ToArray().ForEach(s => dic.Remove(s));
        //    return dic;
        //}

        /// <summary>
        /// 获得程序集所在的目录
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <returns>指定程序集所在的位置目录</returns>
        public static string GetLocation(this System.Reflection.Assembly assembly)
        {
            return System.IO.Path.GetDirectoryName(assembly.Location);
        }

        /// <summary>
        /// 获得程序集版本信息
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <returns>指定程序集的版本</returns>
        public static Version GetVersion(this System.Reflection.Assembly assembly)
        {
            return assembly.GetName().Version;
        }

        /// <summary>
        /// 获得程序集的文件信息
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <returns><see cref="T:System.Diagnostics.FileVersionInfo"/></returns>
        public static System.Diagnostics.FileVersionInfo GetFileVersionInfo(this System.Reflection.Assembly assembly)
        {
            return System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
        }

        /// <summary>
        /// 对类型列表进行过滤。
        /// </summary>
        /// <typeparam name="T">过滤的类型，可以根据基类、接口或自定义属性进行过滤</typeparam>
        /// <param name="typeList">要过滤的类型列表</param>
        /// <param name="imp">对应的类型</param>
        /// <returns>过滤后的类型列表</returns>
        public static IEnumerable<Type> FilterType<T>(this IEnumerable<Type> typeList)
        {
            return FilterType<T>(typeList, false);
        }

        /// <summary>
        /// 对类型列表进行过滤。
        /// </summary>
        /// <typeparam name="T">过滤的类型，可以根据基类、接口或自定义属性进行过滤</typeparam>
        /// <param name="typeList">要过滤的类型列表</param>
        /// <param name="imp">对应的类型</param>
        /// <param name="ignoreAttribute">是否忽略自定义属性；如果为 true，则传入自定义属性时，不会按照自定义属性过滤</param>
        /// <returns>过滤后的类型列表</returns>
        public static IEnumerable<Type> FilterType<T>(this IEnumerable<Type> typeList, bool ignoreAttribute)
        {
            var t = typeof(T);

            if (t.IsInterface)
            {
                return typeList.Where(s => s.GetInterface(t.FullName) != null);
            }
            else if (!ignoreAttribute && t.IsClass && t.IsSubclassOf(typeof(Attribute)))
            {
                return typeList.Where(s => !s.GetCustomAttributes(t, true).IsNullOrEmpty());
            }
            else if (t.IsClass)
            {
                return typeList.Where(s => s.IsSubclassOf(t));
            }

            return typeList;
        }

        /// <summary>
        /// 获得类的完整名称（含程序集名称）
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetTypeFullNameWithAssembly(this Type type)
        {
            return type.FullName + ", " + System.IO.Path.GetFileNameWithoutExtension(type.Assembly.Location);
        }

        ///// <summary>
        ///// 获得自定义属性
        ///// </summary>
        ///// <typeparam name="T">类型</typeparam>
        ///// <param name="type">自定义属性类型</param>
        ///// <param name="inherit">是否继承</param>
        ///// <returns></returns>
        //public static T[] GetCustomerAttributes<T>(this ICustomAttributeProvider type, bool inherit) where T : Attribute
        //{
        //    if (type == null)
        //        return null;

        //    return type.GetCustomAttributes(typeof(T), inherit).Cast<T>().ToArray();
        //}

        ///// <summary>
        ///// 获得自定义属性
        ///// </summary>
        ///// <typeparam name="T">类型</typeparam>
        ///// <param name="type">自定义属性类型</param>
        ///// <returns></returns>
        //public static T[] GetCustomerAttributes<T>(this ICustomAttributeProvider type) where T : Attribute
        //{
        //    if (type == null)
        //        return null;

        //    return type.GetCustomAttributes(typeof(T), false).Cast<T>().ToArray();
        //}

        ///// <summary>
        ///// 获得程序集是否是调试版本编译的
        ///// </summary>
        ///// <param name="assembly">程序集</param>
        ///// <returns>如果是调试版本，返回 true；否则返回false。</returns>
        //public static bool IsDebugAssembly(this Assembly assembly)
        //{
        //    if (assembly == null)
        //        return false;

        //    var debugAttributes = assembly.GetCustomerAttributes<System.Diagnostics.DebuggableAttribute>();
        //    return !debugAttributes.IsNullOrEmpty() && debugAttributes[0].IsJITTrackingEnabled;
        //}

        #endregion Reflection

        #region Common

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="R">结果类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <returns><typeparamref name="R"/></returns>
        public static R SelectValue<T, R>(this T obj, Func<T, R> selector) where T : class
        {
            if (obj == null) return default(R);

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="R">结果类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <param name="defaultValue">返回的默认值</param>
        /// <returns><typeparamref name="R"/></returns>
        public static R SelectValue<T, R>(this T obj, Func<T, R> selector, R defaultValue) where T : class
        {
            if (obj == null) return defaultValue;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <returns><see cref="T:System.String"/></returns>
        public static string SelectValue<T>(this T obj, Func<T, string> selector) where T : class
        {
            if (obj == null) return null;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <param name="defaultValue">返回的默认值</param>
        /// <returns><see cref="T:System.String"/></returns>
        public static string SelectValue<T>(this T obj, Func<T, string> selector, string defaultValue) where T : class
        {
            if (obj == null) return defaultValue;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <returns><see cref="T:System.DateTime"/></returns>
        public static DateTime SelectValue<T>(this T obj, Func<T, DateTime> selector) where T : class
        {
            if (obj == null) return DateTime.MinValue;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <param name="defaultValue">返回的默认值</param>
        /// <returns><see cref="T:System.DateTime"/></returns>
        public static DateTime SelectValue<T>(this T obj, Func<T, DateTime> selector, DateTime defaultValue) where T : class
        {
            if (obj == null) return defaultValue;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <returns><see cref="T:System.Int32"/></returns>
        public static int SelectValue<T>(this T obj, Func<T, int> selector) where T : class
        {
            if (obj == null) return 0;

            return selector(obj);
        }

        /// <summary>
        /// 根据对象选择值，如果为空，则返回默认值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="selector">选择器</param>
        /// <param name="defaultValue">返回的默认值</param>
        /// <returns><see cref="T:System.Int32"/></returns>
        public static int SelectValue<T>(this T obj, Func<T, int> selector, int defaultValue) where T : class
        {
            if (obj == null) return defaultValue;

            return selector(obj);
        }

        #endregion Common

        #region Uri

        /// <summary>
        /// 获得指定地址中的文件名
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static string GetFileName(this Uri uri)
        {
            if (uri == null) return string.Empty;

            var path = uri.LocalPath;
            var index = path.LastIndexOf("/");
            return index == -1 ? path : path.Substring(index + 1);
        }

        private static readonly Regex _topLevelHostReg = new Regex(@"[-a-zA-Z\d]+\.[-a-zA-Z\d]+$", RegexOptions.IgnoreCase);

        /// <summary>
        /// 获得一个域名空间的顶级主机地址
        /// </summary>
        /// <param name="uri">完整域名</param>
        /// <returns><see cref="T:System.String"/></returns>
        public static string GetTopLevelHost(this Uri uri)
        {
            var m = _topLevelHostReg.Match(uri.Host);
            if (m.Success) return m.Value;
            else return uri.Host;
        }

        #endregion Uri

        #region Stream

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int16"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int16"/></returns>
        public static ushort ReadUInt16(this System.IO.Stream stream)
        {
            return BitConverter.ToUInt16(stream.ReadBuffer(2), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int32"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int32"/></returns>
        public static uint ReadUInt32(this Stream stream)
        {
            return BitConverter.ToUInt32(stream.ReadBuffer(4), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int64"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int64"/></returns>
        public static ulong ReadUInt64(this Stream stream)
        {
            return BitConverter.ToUInt64(stream.ReadBuffer(8), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int16"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int16"/></returns>
        public static short ReadInt16(this System.IO.Stream stream)
        {
            return BitConverter.ToInt16(stream.ReadBuffer(2), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int32"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int32"/></returns>
        public static int ReadInt32(this Stream stream)
        {
            return BitConverter.ToInt32(stream.ReadBuffer(4), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int64"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int64"/></returns>
        public static long ReadInt64(this Stream stream)
        {
            return BitConverter.ToInt64(stream.ReadBuffer(8), 0);
        }

        /// <summary>
        /// 从流中读入一个 <see cref="T:System.Int64"/>
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <returns>读取的 <see cref="T:System.Int64"/></returns>
        public static double ReadDouble(this Stream stream)
        {
            return BitConverter.ToDouble(stream.ReadBuffer(sizeof(double)), 0);
        }

        /// <summary>
        /// 从流中读入一个缓冲数组
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <param name="length">读取的字节长度</param>
        /// <returns>缓冲数组</returns>
        public static byte[] ReadBuffer(this Stream stream, int length)
        {
            var count = 0;

            return stream.ReadBuffer(length, out count);
        }

        /// <summary>
        /// 从流中读入一个缓冲数组
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <param name="length">读取的字节长度</param>
        /// <param name="readedBytesCount">返回已经读取到的长度</param>
        /// <returns>缓冲数组</returns>
        public static byte[] ReadBuffer(this Stream stream, int length, out int readedBytesCount)
        {
            var buffer = new byte[length];
            readedBytesCount = stream.Read(buffer, 0, buffer.Length);

            return buffer;
        }

        /// <summary>
        /// 从流中读入一个缓冲数组
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <param name="buffer">缓冲数组</param>
        /// <returns>缓冲数组</returns>
        [Obsolete("此函数没有很大的意义，将会被移除。This method will be removed soon due to no means.")]
        public static byte[] FillBuffer(this Stream stream, byte[] buffer)
        {
            if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
            {
                throw new Exception();
            }

            return buffer;
        }

        /// <summary>
        /// 读取所有的数据到内存流中
        /// </summary>
        /// <param name="stream">要读取的流</param>
        /// <param name="readBufferSize">读取的缓冲区长度，默认为 4KB</param>
        /// <returns>包含所有数据的 <see cref="MemoryStream"/> </returns>
        [CanBeNull]
        public static MemoryStream ReadToEnd([NotNull] this Stream stream, int readBufferSize = 0x400)
        {
            if (!stream.CanRead)
                return null;

            var end = stream as MemoryStream;
            if (end != null)
                return end;

            var ms = new MemoryStream();
            var buffer = new byte[readBufferSize];
            var count = 0;
            while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
                ms.Write(buffer, 0, count);
            ms.Flush();
            ms.Seek(0, SeekOrigin.Begin);

            return ms;
        }

        /// <summary>
        /// 压缩原始流
        /// </summary>
        /// <param name="stream">要写入的目标流</param>
        /// <returns>供写入的压缩流</returns>
        public static Stream Zip(this Stream stream)
        {
            return new System.IO.Compression.GZipStream(stream, CompressionMode.Compress);
        }

        /// <summary>
        /// 解压缩原始流
        /// </summary>
        /// <param name="stream">供读取的压缩流</param>
        /// <returns>供读取的解压缩流</returns>
        public static Stream UnZip(this Stream stream)
        {
            return new GZipStream(stream, CompressionMode.Decompress);
        }

        /// <summary>
        /// 获得当前流位置的显示字符串格式
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string GetPositionString(this Stream stream)
        {
            return string.Format("0x{0:X8}", stream.Position);
        }

        /// <summary>
        /// 将指定的缓冲数组全部写入流中
        /// </summary>
        /// <param name="stream">目标流</param>
        /// <param name="buffer">缓冲数组</param>
        public static T Write<T>(this T stream, byte[] buffer) where T : Stream
        {
            stream.Write(buffer, 0, buffer.Length);
            return stream;
        }

        /// <summary>
        /// 将指定的缓冲数组全部写入流中
        /// </summary>
        /// <param name="stream">目标流</param>
        /// <param name="buffer">缓冲数组</param>
        public static T Write<T>(this T stream, IEnumerable<byte> buffer) where T : Stream
        {
            stream.Write(buffer.ToArray());
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, int value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, uint value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, short value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, ushort value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, long value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        /// <summary>
        /// 将目标值写入流中
        /// </summary>
        /// <param name="stream">当前流</param>
        /// <param name="value">值</param>
        public static T Write<T>(this T stream, ulong value) where T : Stream
        {
            stream.Write(BitConverter.GetBytes(value));
            return stream;
        }

        #endregion Stream

        #region 其它

        /// <summary>
        /// 对指定的数据进行条件判断，如果符合要求则执行
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="value">值</param>
        /// <param name="eval">表达式</param>
        /// <param name="action">执行方法</param>
        public static void ExecuteIf<T>(this T value, Func<T, bool> eval, Action<T> action)
        {
            if (eval(value)) action(value);
        }

        /// <summary>
        /// 对指定的数据进行条件判断，如果大于0则执行
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="action">执行方法</param>
        public static void ExecuteIfPositive(this int value, Action<int> action)
        {
            if (value > 0) action(value);
        }

        /// <summary>
        /// 对指定的数据进行条件判断，如果不为空字符串则执行
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="action">执行方法</param>
        public static void ExecuteIfNotEmpty(this string value, Action<string> action)
        {
            if (!string.IsNullOrEmpty(value)) action(value);
        }

        /// <summary>
        /// 对指定的数据进行条件判断，如果不为null则执行
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="action">执行方法</param>
        public static void ExecuteIfNotEmpty<T>(this T value, Action<T> action) where T : class
        {
            if (value != null) action(value);
        }

        /// <summary>
        /// 双重加锁执行
        /// </summary>
        /// <param name="obj">当前锁对象</param>
        /// <param name="condition">条件，返回false则不执行</param>
        /// <param name="action">执行的操作</param>
        public static void LockExecute(this object obj, Func<bool> condition, Action action)
        {
            if (action == null || obj == null) return;

            if (condition == null || condition())
            {
                lock (obj)
                {
                    if (condition == null || condition())
                    {
                        action();
                    }
                }
            }
        }

        #endregion 其它

        #region Cast 映射

        /// <summary>
        /// 转换匿名类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="o"></param>
        /// <param name="example"></param>
        /// <returns></returns>
        public static T TolerantCast<T>(this object o, T example) where T : class
        {
            IComparer<string> comparer = StringComparer.CurrentCultureIgnoreCase;
            //Get constructor with lowest number of parameters and its parameters
            var constructor = typeof(T).GetConstructors(
                BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
                ).OrderBy(c => c.GetParameters().Length).First();
            var parameters = constructor.GetParameters();

            //Get properties of input object
            var sourceProperties = new List<PropertyInfo>(o.GetType().GetProperties());

            if (parameters.Length > 0)
            {
                var values = new object[parameters.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    Type t = parameters[i].ParameterType;
                    //See if the current parameter is found as a property in the input object
                    var source = sourceProperties.Find(delegate(PropertyInfo item)
                    {
                        return comparer.Compare(item.Name, parameters[i].Name) == 0;
                    });

                    //See if the property is found, is readable, and is not indexed
                    if (source != null && source.CanRead &&
                        source.GetIndexParameters().Length == 0)
                    {
                        //See if the types match.
                        if (source.PropertyType == t)
                        {
                            //Get the value from the property in the input object and save it for use
                            //in the constructor call.
                            values[i] = source.GetValue(o, null);
                            continue;
                        }
                        else
                        {
                            //See if the property value from the input object can be converted to
                            //the parameter type
                            try
                            {
                                values[i] = Convert.ChangeType(source.GetValue(o, null), t);
                                continue;
                            }
                            catch
                            {
                                //Impossible. Forget it then.
                            }
                        }
                    }
                    //If something went wrong (i.e. property not found, or property isn't
                    //converted/copied), get a default value.
                    values[i] = t.IsValueType ? Activator.CreateInstance(t) : null;
                }
                //Call the constructor with the collected values and return it.
                return (T)constructor.Invoke(values);
            }
            //Call the constructor without parameters and return the it.
            return (T)constructor.Invoke(null);
        }

        /// <summary>
        /// 	Converts an object to the specified target type or returns the default value if
        ///     those 2 types are not convertible.
        ///     <para>
        ///     If the <paramref name="value"/> can't be convert even if the types are 
        ///     convertible with each other, an exception is thrown.</para>
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <returns>The target type</returns>
        public static T ConvertTo<T>(this object value)
        {
            return value.Cast(default(T));
        }

        /// <summary>
        /// 	Converts an object to the specified target type or returns the default value.
        ///     <para>Any exceptions are ignored. </para>
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <returns>The target type</returns>
        public static T CastAndIgnoreException<T>(this object value)
        {
            return value.CastAndIgnoreException(default(T));
        }

        /// <summary>
        /// 	Converts an object to the specified target type or returns the default value.
        ///     <para>Any exceptions are ignored. </para>
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <param name = "defaultValue">The default value.</param>
        /// <returns>The target type</returns>
        public static T CastAndIgnoreException<T>(this object value, T defaultValue)
        {
            return value.Cast(defaultValue, true);
        }

        /// <summary>
        /// 	Converts an object to the specified target type or returns the default value if
        ///     those 2 types are not convertible.
        ///     <para>
        ///     If the <paramref name="value"/> can't be convert even if the types are 
        ///     convertible with each other, an exception is thrown.</para>
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <param name = "defaultValue">The default value.</param>
        /// <returns>The target type</returns>
        public static T Cast<T>(this object value, T defaultValue)
        {
            if (value != null)
            {
                var targetType = typeof(T);

                if (value.GetType() == targetType) return (T)value;

                var converter = TypeDescriptor.GetConverter(value);
                if (converter != null)
                {
                    if (converter.CanConvertTo(targetType))
                        return (T)converter.ConvertTo(value, targetType);
                }

                converter = TypeDescriptor.GetConverter(targetType);
                if (converter != null)
                {
                    if (converter.CanConvertFrom(value.GetType()))
                        return (T)converter.ConvertFrom(value);
                }
            }
            return defaultValue;
        }

        /// <summary>
        /// 	Converts an object to the specified target type or returns the default value if
        ///     those 2 types are not convertible.
        ///     <para>Any exceptions are optionally ignored (<paramref name="ignoreException"/>).</para>
        ///     <para>
        ///     If the exceptions are not ignored and the <paramref name="value"/> can't be convert even if 
        ///     the types are convertible with each other, an exception is thrown.</para>
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <param name = "defaultValue">The default value.</param>
        /// <param name = "ignoreException">if set to <c>true</c> ignore any exception.</param>
        /// <returns>The target type</returns>
        public static T Cast<T>(this object value, T defaultValue, bool ignoreException)
        {
            if (ignoreException)
            {
                try
                {
                    return value.ConvertTo<T>();
                }
                catch
                {
                    return defaultValue;
                }
            }
            return value.ConvertTo<T>();
        }

        /// <summary>
        /// 	Determines whether the value can (in theory) be converted to the specified target type.
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <returns>
        /// 	<c>true</c> if this instance can be convert to the specified target type; otherwise, <c>false</c>.
        /// </returns>
        public static bool CanCast<T>(this object value)
        {
            if (value != null)
            {
                var targetType = typeof(T);

                var converter = TypeDescriptor.GetConverter(value);
                if (converter != null)
                {
                    if (converter.CanConvertTo(targetType))
                        return true;
                }

                converter = TypeDescriptor.GetConverter(targetType);
                if (converter != null)
                {
                    if (converter.CanConvertFrom(value.GetType()))
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 	Converts the specified value to a different type.
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "value">The value.</param>
        /// <returns>An universal converter suppliying additional target conversion methods</returns>
        /// <example>
        /// 	<code>
        /// 		var value = "123";
        /// 		var numeric = value.ConvertTo().ToInt32();
        /// 	</code>
        /// </example>
        public static IConverter<T> Cast<T>(this T value)
        {
            return new Converter<T>(value);
        }

        /// <summary>
        ///  将对象转换成目标类型
        /// 	Cast an object to the given type. Usefull especially for anonymous types.
        /// </summary>
        /// <param name="obj">被转换对象The object to be cast</param>
        /// <param name="targetType">目标类型The type to cast to</param>
        /// <returns>
        /// 	the casted type or null if casting is not possible.
        /// </returns>
        /// <remarks>
        /// 	Contributed by Michael T, http://about.me/MichaelTran
        /// </remarks>
        public static object DynamicCast(this object obj, Type targetType)
        {
            // First, it might be just a simple situation
            if (targetType.IsAssignableFrom(obj.GetType()))
                return obj;

            // If not, we need to find a cast operator. The operator
            // may be explicit or implicit and may be included in
            // either of the two types...
            const BindingFlags pubStatBinding = BindingFlags.Public | BindingFlags.Static;
            var originType = obj.GetType();
            String[] names = { "op_Implicit", "op_Explicit" };

            var castMethod =
                    targetType.GetMethods(pubStatBinding).Union(originType.GetMethods(pubStatBinding)).FirstOrDefault(
                            itm => itm.ReturnType.Equals(targetType) && itm.GetParameters().Length == 1 && itm.GetParameters()[0].ParameterType.IsAssignableFrom(originType) && names.Contains(itm.Name));
            if (null != castMethod)
                return castMethod.Invoke(null, new[] { obj });
            throw new InvalidOperationException(
                    String.Format(
                            "No matching cast operator found from {0} to {1}.",
                            originType.Name,
                            targetType.Name));
        }

        /// <summary>
        /// Cast an object to the given type. Usefull especially for anonymous types.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">The object to be cast</param>
        /// <returns>
        /// the casted type or null if casting is not possible.
        /// </returns>
        /// <remarks>
        /// Contributed by Michael T, http://about.me/MichaelTran
        /// </remarks>
        public static T CastAs<T>(this object obj) where T : class, new()
        {
            return obj as T;
        }
        #endregion 转换

        #region 反射

        #region Method 方法

        /// <summary>
        /// 	Dynamically invokes a method using reflection
        /// </summary>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "methodName">The name of the method.</param>
        /// <param name = "parameters">The parameters passed to the method.</param>
        /// <returns>The return value</returns>
        /// <example>
        /// 	<code>
        /// 		var type = Type.GetType("System.IO.FileInfo, mscorlib");
        /// 		var file = type.CreateInstance(@"c:\autoexec.bat");
        /// 		if(file.GetPropertyValue&lt;bool&gt;("Exists")) {
        /// 		var reader = file.InvokeMethod&lt;StreamReader&gt;("OpenText");
        /// 		Console.WriteLine(reader.ReadToEnd());
        /// 		reader.Close();
        /// 		}
        /// 	</code>
        /// </example>
        public static object InvokeMethod(this object obj, string methodName, params object[] parameters)
        {
            return InvokeMethod<object>(obj, methodName, parameters);
        }

        /// <summary>
        /// 	Dynamically invokes a method using reflection and returns its value in a typed manner
        /// </summary>
        /// <typeparam name = "T">The expected return data types</typeparam>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "methodName">The name of the method.</param>
        /// <param name = "parameters">The parameters passed to the method.</param>
        /// <returns>The return value</returns>
        /// <example>
        /// 	<code>
        /// 		var type = Type.GetType("System.IO.FileInfo, mscorlib");
        /// 		var file = type.CreateInstance(@"c:\autoexec.bat");
        /// 		if(file.GetPropertyValue&lt;bool&gt;("Exists")) {
        /// 		var reader = file.InvokeMethod&lt;StreamReader&gt;("OpenText");
        /// 		Console.WriteLine(reader.ReadToEnd());
        /// 		reader.Close();
        /// 		}
        /// 	</code>
        /// </example>
        public static T InvokeMethod<T>(this object obj, string methodName, params object[] parameters)
        {
            var type = obj.GetType();
            var method = type.GetMethod(methodName, parameters.Select(o => o.GetType()).ToArray());

            if (method == null)
                throw new ArgumentException(string.Format("Method '{0}' not found.", methodName), methodName);

            var value = method.Invoke(obj, parameters);
            return (value is T ? (T)value : default(T));
        }

        #endregion //Method

        #region PropertyInfo 公共属性

        /// <summary>
        /// 	Dynamically retrieves a property value.
        /// </summary>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "propertyName">The Name of the property.</param>
        /// <returns>The property value.</returns>
        /// <example>
        /// 	<code>
        /// 		var type = Type.GetType("System.IO.FileInfo, mscorlib");
        /// 		var file = type.CreateInstance(@"c:\autoexec.bat");
        /// 		if(file.GetPropertyValue&lt;bool&gt;("Exists")) {
        /// 		var reader = file.InvokeMethod&lt;StreamReader&gt;("OpenText");
        /// 		Console.WriteLine(reader.ReadToEnd());
        /// 		reader.Close();
        /// 		}
        /// 	</code>
        /// </example>
        public static object GetPropertyValue(this object obj, string propertyName)
        {
            return GetPropertyValue<object>(obj, propertyName, null);
        }

        /// <summary>
        /// 	Dynamically retrieves a property value.
        /// </summary>
        /// <typeparam name = "T">The expected return data type</typeparam>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "propertyName">The Name of the property.</param>
        /// <returns>The property value.</returns>
        /// <example>
        /// 	<code>
        /// 		var type = Type.GetType("System.IO.FileInfo, mscorlib");
        /// 		var file = type.CreateInstance(@"c:\autoexec.bat");
        /// 		if(file.GetPropertyValue&lt;bool&gt;("Exists")) {
        /// 		var reader = file.InvokeMethod&lt;StreamReader&gt;("OpenText");
        /// 		Console.WriteLine(reader.ReadToEnd());
        /// 		reader.Close();
        /// 		}
        /// 	</code>
        /// </example>
        public static T GetPropertyValue<T>(this object obj, string propertyName)
        {
            return GetPropertyValue(obj, propertyName, default(T));
        }

        /// <summary>
        /// 	Dynamically retrieves a property value.
        /// </summary>
        /// <typeparam name = "T">The expected return data type</typeparam>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "propertyName">The Name of the property.</param>
        /// <param name = "defaultValue">The default value to return.</param>
        /// <returns>The property value.</returns>
        /// <example>
        /// 	<code>
        /// 		var type = Type.GetType("System.IO.FileInfo, mscorlib");
        /// 		var file = type.CreateInstance(@"c:\autoexec.bat");
        /// 		if(file.GetPropertyValue&lt;bool&gt;("Exists")) {
        /// 		var reader = file.InvokeMethod&lt;StreamReader&gt;("OpenText");
        /// 		Console.WriteLine(reader.ReadToEnd());
        /// 		reader.Close();
        /// 		}
        /// 	</code>
        /// </example>
        public static T GetPropertyValue<T>(this object obj, string propertyName, T defaultValue)
        {
            var type = obj.GetType();
            var property = type.GetProperty(propertyName);

            if (property == null)
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);

            var value = property.GetValue(obj, null);
            return (value is T ? (T)value : defaultValue);
        }

        static object GetValue(object o, PropertyInfo propertyInfo)
        {
            object value;
            try
            {
                value = propertyInfo.GetValue(o, null);
            }
            catch
            {
                try
                {
                    value = propertyInfo.GetValue(o,
                            new object[]
					{
						0
					});
                }
                catch
                {
                    value = null;
                }
            }
            return value;
        }


        /// <summary>
        /// 	Dynamically sets a property value.
        /// </summary>
        /// <param name = "obj">The object to perform on.</param>
        /// <param name = "propertyName">The Name of the property.</param>
        /// <param name = "value">The value to be set.</param>
        public static void SetPropertyValue(this object obj, string propertyName, object value)
        {
            var type = obj.GetType();
            var property = type.GetProperty(propertyName);

            if (property == null)
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);
            if (!property.CanWrite)
                throw new ArgumentException(string.Format("Property '{0}' does not allow writes.", propertyName), propertyName);
            property.SetValue(obj, value, null);
        }


        /// <summary>
        /// Copies the readable and writable public property values from the source object to the target
        /// </summary>
        /// <remarks>The source and target objects must be of the same type.</remarks>
        /// <param name="target">The target object</param>
        /// <param name="source">The source object</param>
        public static void CopyPropertiesFrom(this object target, object source)
        {
            CopyPropertiesFrom(target, source, string.Empty);
        }

        /// <summary>
        /// Copies the readable and writable public property values from the source object to the target
        /// </summary>
        /// <remarks>The source and target objects must be of the same type.</remarks>
        /// <param name="target">The target object</param>
        /// <param name="source">The source object</param>
        /// <param name="ignoreProperty">A single property name to ignore</param>
        public static void CopyPropertiesFrom(this object target, object source, string ignoreProperty)
        {
            CopyPropertiesFrom(target, source, new[] { ignoreProperty });
        }

        /// <summary>
        /// Copies the readable and writable public property values from the source object to the target
        /// </summary>
        /// <remarks>The source and target objects must be of the same type.</remarks>
        /// <param name="target">The target object</param>
        /// <param name="source">The source object</param>
        /// <param name="ignoreProperties">An array of property names to ignore</param>
        public static void CopyPropertiesFrom(this object target, object source, string[] ignoreProperties)
        {
            // Get and check the object types
            Type type = source.GetType();
            if (target.GetType() != type)
            {
                throw new ArgumentException("The source type must be the same as the target");
            }

            // Build a clean list of property names to ignore
            var ignoreList = new List<string>();
            foreach (string item in ignoreProperties)
            {
                if (!string.IsNullOrEmpty(item) && !ignoreList.Contains(item))
                {
                    ignoreList.Add(item);
                }
            }

            // Copy the properties
            foreach (PropertyInfo property in type.GetProperties())
            {
                if (property.CanWrite
                    && property.CanRead
                    && !ignoreList.Contains(property.Name))
                {
                    object val = property.GetValue(source, null);
                    property.SetValue(target, val, null);
                }
            }
        }

        /// <summary>
        /// Returns a string representation of the objects property values
        /// </summary>
        /// <param name="source">The object for the string representation</param>
        /// <returns>A string</returns>
        public static string ToPropertiesString(this object source)
        {
            return ToPropertiesString(source, Environment.NewLine);
        }

        /// <summary>
        /// Returns a string representation of the objects property values
        /// </summary>
        /// <param name="source">The object for the string representation</param>
        /// <param name="delimiter">The line terminstor string to use between properties</param>
        /// <returns>A string</returns>
        public static string ToPropertiesString(this object source, string delimiter)
        {
            if (source == null)
            {
                return string.Empty;
            }

            Type type = source.GetType();

            var sb = new StringBuilder(type.Name);
            sb.Append(delimiter);

            foreach (PropertyInfo property in type.GetProperties())
            {
                if (property.CanWrite
                    && property.CanRead)
                {
                    object val = property.GetValue(source, null);
                    sb.Append(property.Name);
                    sb.Append(": ");
                    sb.Append(val == null ? "[NULL]" : val.ToString());
                    sb.Append(delimiter);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// Serializes the object into an XML string, using the encoding method specified in
        /// <see cref="ExtensionMethodsSettings.DefaultEncoding"/>
        /// </summary>
        /// <remarks>
        /// The object to be serialized should be decorated with the 
        /// <see cref="SerializableAttribute"/>, or implement the <see cref="ISerializable"/> interface.
        /// </remarks>
        /// <param name="source">The object to serialize</param>
        /// <returns>An XML encoded string representation of the source object</returns>
        public static string ToXml(this object source)
        {
            return ToXml(source, Encoding.UTF8);
        }

        /// <summary>
        /// Serializes the object into an XML string
        /// </summary>
        /// <remarks>
        /// The object to be serialized should be decorated with the 
        /// <see cref="SerializableAttribute"/>, or implement the <see cref="ISerializable"/> interface.
        /// </remarks>
        /// <param name="source">The object to serialize</param>
        /// <param name="encoding">The Encoding scheme to use when serializing the data to XML</param>
        /// <returns>An XML encoded string representation of the source object</returns>
        public static string ToXml(this object source, Encoding encoding)
        {
            if (source == null)
            {
                throw new ArgumentException("The source object cannot be null.");
            }

            if (encoding == null)
            {
                throw new Exception("You must specify an encoder to use for serialization.");
            }

            using (var stream = new MemoryStream())
            {
                var serializer = new XmlSerializer(source.GetType());
                serializer.Serialize(stream, source);
                stream.Position = 0;
                return encoding.GetString(stream.ToArray());
            }
        }

        /// <summary>
        /// Serializes the object into an XML string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="this"></param>
        /// <returns></returns>
        public static string ToXml<T>(this T @this)
        {
            if (@this == null) throw new NullReferenceException();

            XmlSerializer ser = new XmlSerializer(typeof(T));

            using (StringWriter writer = new StringWriter())
            {
                ser.Serialize(writer, @this);
                return writer.ToString();
            }
        }
        #endregion //Property

        #region FieldInfo 公共字段
        public static FieldInfo FindMemberField(FieldInfo[] fields, string memberName)
        {
           IEnumerable<FieldInfo> targets = fields.Where(x => !x.IsSpecialName && x.Name.Equals(memberName, StringComparison.CurrentCultureIgnoreCase));
           return targets.IsNullOrEmpty()?null:targets.First();
        }
        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        public static string GetDescriptionAttribute(this FieldInfo field)
        {
            string description = string.Empty;
            description = field.GetAttribute<DescriptionAttribute>(false).Description;
            return description;
        }
        #endregion //FieldInfo 公共字段

        #region MemberInfo 成员特性
        #endregion

        #region Attribute 特性

        /// <summary>
        /// 	Gets the first matching attribute defined on the data type.
        /// </summary>
        /// <typeparam name = "T">The attribute type tp look for.</typeparam>
        /// <param name = "obj">The object to look on.</param>
        /// <returns>The found attribute</returns>
        public static T GetAttribute<T>(this object obj) where T : Attribute
        {
            return GetAttribute<T>(obj, true);
        }

        /// <summary>
        /// 	Gets the first matching attribute defined on the data type.
        /// </summary>
        /// <typeparam name = "T">The attribute type tp look for.</typeparam>
        /// <param name = "obj">The object to look on.</param>
        /// <param name = "includeInherited">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>The found attribute</returns>
        public static T GetAttribute<T>(this object obj, bool includeInherited) where T : Attribute
        {
            var type = (obj as Type ?? obj.GetType());
            var attributes = type.GetCustomAttributes(typeof(T), includeInherited);
            return attributes.FirstOrDefault() as T;
        }

        /// <summary>
        /// 	Gets all matching attribute defined on the data type.
        /// </summary>
        /// <typeparam name = "T">The attribute type tp look for.</typeparam>
        /// <param name = "obj">The object to look on.</param>
        /// <returns>The found attributes</returns>
        public static IEnumerable<T> GetAttributes<T>(this object obj) where T : Attribute
        {
            return GetAttributes<T>(obj, false);
        }

        /// <summary>
        /// 	Gets all matching attribute defined on the data type.
        /// </summary>
        /// <typeparam name = "T">The attribute type tp look for.</typeparam>
        /// <param name = "obj">The object to look on.</param>
        /// <param name = "includeInherited">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>The found attributes</returns>
        public static IEnumerable<T> GetAttributes<T>(this object obj, bool includeInherited) where T : Attribute
        {
            return (obj as Type ?? obj.GetType()).GetCustomAttributes(typeof(T), includeInherited).OfType<T>().Select(attribute => attribute);
        }

        #endregion  Attribute

        #endregion //反射

        #region Bool 判断

        #region Type 类型或集成
        /// <summary>
        /// 是否是..类型
        /// 	Determines whether the object is exactly of the passed generic type.
        /// </summary>
        /// <typeparam name = "T">The target type.</typeparam>
        /// <param name = "obj">The object to check.</param>
        /// <returns>
        /// 	<c>true</c> if the object is of the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsOfType<T>(this object obj)
        {
            return obj.IsOfType(typeof(T));
        }

        /// <summary>
        /// 	Determines whether the object is excactly of the passed type
        /// </summary>
        /// <param name = "obj">The object to check.</param>
        /// <param name = "type">The target type.</param>
        /// <returns>
        /// 	<c>true</c> if the object is of the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsOfType(this object obj, Type type)
        {
            return (obj.GetType().Equals(type));
        }

        /// <summary>
        /// 	Determines whether the object is of the passed generic type or inherits from it.
        /// </summary>
        /// <typeparam name = "T">The target type.</typeparam>
        /// <param name = "obj">The object to check.</param>
        /// <returns>
        /// 	<c>true</c> if the object is of the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsOfTypeOrInherits<T>(this object obj)
        {
            return obj.IsOfTypeOrInherits(typeof(T));
        }

        /// <summary>
        /// 	Determines whether the object is of the passed type or inherits from it.
        /// </summary>
        /// <param name = "obj">The object to check.</param>
        /// <param name = "type">The target type.</param>
        /// <returns>
        /// 	<c>true</c> if the object is of the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsOfTypeOrInherits(this object obj, Type type)
        {
            var objectType = obj.GetType();
            do
            {
                if (objectType.Equals(type))
                    return true;
                if ((objectType == objectType.BaseType) || (objectType.BaseType == null))
                    return false;
                objectType = objectType.BaseType;
            } while (true);
        }
        #endregion

        #region AssignableTo 直接或间接实现接口
        /// <summary>
        /// 	Determines whether the object is assignable to the passed generic type.
        /// </summary>
        /// <typeparam name = "T">The target type.</typeparam>
        /// <param name = "obj">The object to check.</param>
        /// <returns>
        /// 	<c>true</c> if the object is assignable to the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsAssignableTo<T>(this object obj)
        {
            return obj.IsAssignableTo(typeof(T));
        }

        /// <summary>
        /// 	Determines whether the object is assignable to the passed type.
        /// </summary>
        /// <param name = "obj">The object to check.</param>
        /// <param name = "type">The target type.</param>
        /// <returns>
        /// 	<c>true</c> if the object is assignable to the specified type; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsAssignableTo(this object obj, Type type)
        {
            var objectType = obj.GetType();
            //判断两个类型的关系  
            //类型可以是父类，接口  
            //用法：父类.IsAssignableFrom(子类)  
            return type.IsAssignableFrom(objectType);
        }
        #endregion //Assignable

        #region IsNull
        /// <summary>
        /// 	Returns TRUE, if specified target reference is equals with null reference.
        /// 	Othervise returns FALSE.
        /// </summary>
        /// <param name = "target">Target reference. Can be null.</param>
        /// <remarks>
        /// 	Some types has overloaded '==' and '!=' operators.
        /// 	So the code "null == ((MyClass)null)" can returns <c>false</c>.
        /// 	The most correct way how to test for null reference is using "System.Object.ReferenceEquals(object, object)" method.
        /// 	However the notation with ReferenceEquals method is long and uncomfortable - this extension method solve it.
        /// 
        /// 	Contributed by tencokacistromy, http://www.codeplex.com/site/users/view/tencokacistromy
        /// </remarks>
        /// <example>
        /// 	object someObject = GetSomeObject();
        /// 	if ( someObject.IsNull() ) { /* the someObject is null */ }
        /// 	else { /* the someObject is not null */ }
        /// </example>
        public static bool IsNull(this object target)
        {
            var ret = IsNull<object>(target);
            return ret;
        }

        /// <summary>
        /// 	Returns TRUE, if specified target reference is equals with null reference.
        /// 	Othervise returns FALSE.
        /// </summary>
        /// <typeparam name = "T">Type of target.</typeparam>
        /// <param name = "target">Target reference. Can be null.</param>
        /// <remarks>
        /// 	Some types has overloaded '==' and '!=' operators.
        /// 	So the code "null == ((MyClass)null)" can returns <c>false</c>.
        /// 	The most correct way how to test for null reference is using "System.Object.ReferenceEquals(object, object)" method.
        /// 	However the notation with ReferenceEquals method is long and uncomfortable - this extension method solve it.
        /// 
        /// 	Contributed by tencokacistromy, http://www.codeplex.com/site/users/view/tencokacistromy
        /// </remarks>
        /// <example>
        /// 	MyClass someObject = GetSomeObject();
        /// 	if ( someObject.IsNull() ) { /* the someObject is null */ }
        /// 	else { /* the someObject is not null */ }
        /// </example>
        public static bool IsNull<T>(this T target)
        {
            var result = ReferenceEquals(target, null);
            return result;
        }

        /// <summary>
        /// 	Returns TRUE, if specified target reference is equals with null reference.
        /// 	Othervise returns FALSE.
        /// </summary>
        /// <param name = "target">Target reference. Can be null.</param>
        /// <remarks>
        /// 	Some types has overloaded '==' and '!=' operators.
        /// 	So the code "null == ((MyClass)null)" can returns <c>false</c>.
        /// 	The most correct way how to test for null reference is using "System.Object.ReferenceEquals(object, object)" method.
        /// 	However the notation with ReferenceEquals method is long and uncomfortable - this extension method solve it.
        /// 
        /// 	Contributed by tencokacistromy, http://www.codeplex.com/site/users/view/tencokacistromy
        /// </remarks>
        /// <example>
        /// 	object someObject = GetSomeObject();
        /// 	if ( someObject.IsNotNull() ) { /* the someObject is not null */ }
        /// 	else { /* the someObject is null */ }
        /// </example>
        public static bool IsNotNull(this object target)
        {
            var ret = IsNotNull<object>(target);
            return ret;
        }

        /// <summary>
        /// 	Returns TRUE, if specified target reference is equals with null reference.
        /// 	Othervise returns FALSE.
        /// </summary>
        /// <typeparam name = "T">Type of target.</typeparam>
        /// <param name = "target">Target reference. Can be null.</param>
        /// <remarks>
        /// 	Some types has overloaded '==' and '!=' operators.
        /// 	So the code "null == ((MyClass)null)" can returns <c>false</c>.
        /// 	The most correct way how to test for null reference is using "System.Object.ReferenceEquals(object, object)" method.
        /// 	However the notation with ReferenceEquals method is long and uncomfortable - this extension method solve it.
        /// 
        /// 	Contributed by tencokacistromy, http://www.codeplex.com/site/users/view/tencokacistromy
        /// </remarks>
        /// <example>
        /// 	MyClass someObject = GetSomeObject();
        /// 	if ( someObject.IsNotNull() ) { /* the someObject is not null */ }
        /// 	else { /* the someObject is null */ }
        /// </example>
        public static bool IsNotNull<T>(this T target)
        {
            var result = !ReferenceEquals(target, null);
            return result;
        }
        #endregion //IsNull

        /// <summary>
        /// True if object is value type.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNumericType(this object obj)
        {
            return obj.GetType().IsNumericType();
        }

        /// <summary>
        /// 	Determines whether the object is equal to any of the provided values.
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "obj">The object to be compared.</param>
        /// <param name = "values">The values to compare with the object.</param>
        /// <returns></returns>
        public static bool EqualsAny<T>(this T obj, params T[] values)
        {
            return (Array.IndexOf(values, obj) != -1);
        }

        /// <summary>
        /// 	Determines whether the object is equal to none of the provided values.
        /// </summary>
        /// <typeparam name = "T"></typeparam>
        /// <param name = "obj">The object to be compared.</param>
        /// <param name = "values">The values to compare with the object.</param>
        /// <returns></returns>
        public static bool EqualsNone<T>(this T obj, params T[] values)
        {
            return (obj.EqualsAny(values) == false);
        }

        /// <summary>
        /// 是否需要递归
        /// </summary>
        /// <param name="type"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        static bool NeedRecursion(Type type, object o)
        {
            return o != null && (!type.IsPrimitive && !(o is String || o is DateTime ||
                o is DateTimeOffset || o is TimeSpan || o is Delegate || 
                o is Enum || o is Decimal || o is Guid));
        }
        #endregion Bool 判断


        /// <summary>
        /// 复制一个对象
        /// Perform a deep Copy of the object.
        /// </summary>
        /// <typeparam name="T">The type of object being copied.</typeparam>
        /// <param name="source">The object instance to copy.</param>
        /// <returns>The copied object.</returns>
        public static T Clone<T>(this T source)
        {
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable.", "source");
            }

            // Don't serialize a null object, simply return the default for that object
            if (Object.ReferenceEquals(source, null))
            {
                return default(T);
            }

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }

        /// <summary>
        /// 计算NULL值的深度
        /// Counts and returns the recursive execution of the passed function until it returns null.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item">The item to start peforming on.</param>
        /// <param name="function">The function to be executed.</param>
        /// <returns>The number of executions until the function returned null</returns>
        public static int CountLoopsToNull<T>(this T item, Func<T, T> function) where T : class
        {
            var num = 0;
            while ((item = function(item)) != null)
            {
                num++;
            }
            return num;
        }
    }
}